package com.jotta.client;

import java.util.ArrayList;
import java.util.EventObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnKeyListener;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;

import com.jotta.client.communicate.Configuration;
import com.jotta.client.communicate.DownloadPicturesThread;
import com.jotta.client.communicate.ServerCommunicator;
import com.jotta.client.communicate.StateOfClient;
import com.jotta.client.data.PictureInfo;
import com.jotta.client.dataaccess.DataAccess;
import com.jotta.client.event.SwipeEventListener;
import com.jotta.client.exception.NetworkException;
import com.jotta.client.exception.ServerException;
import com.jotta.client.setting.SettingManager;
import com.jotta.client.utility.Utility;
import com.jotta.client.zoom.TouchImageView;

enum ModeOfRun {
    LOAD_PICTURE, GET_SEVER_INFORMATION, IDLE
}

public class ImageSwiper extends Activity implements Runnable,
        SwipeEventListener, OnClickListener {

    private ProgressDialog m_ProgressDialog;
    private ArrayList<PictureInfo> pictureInfos;
    private String username, password, swipePath, latestFileView;
    private int currentPosition;
    private Bitmap mBitmap;
    private ModeOfRun modeOfRun = ModeOfRun.IDLE;
    private DownloadPicturesThread downloadThread;
    private ImageButton btnBack, btnNext;
    private boolean isSwiping = false;
    private boolean onStop = false;
    private String waitingImageLoad = "";
    private ModeOfSwipe modeOfSwipe;

    private TouchImageView mZoomView;

    private static String TAG = "Jotta_ImageSwiper";

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.image_swiper);

        initialize();

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            swipePath = extras.getString(Configuration.SWIPE_PATH);

            latestFileView = extras.getString(Configuration.FILE_NAME);
            if (swipePath == "")
                swipePath = SettingManager.getInstance().getLatestSwipePath(
                        getPreferences(MODE_PRIVATE));

            if (latestFileView == "")
                latestFileView = SettingManager.getInstance()
                        .getLatestFileView(getPreferences(MODE_PRIVATE));

        }

        username = SettingManager.getInstance().getUsername();
        password = SettingManager.getInstance().getPassword();

        btnBack = (ImageButton) findViewById(R.id.image_view_btnback);
        btnBack.setOnClickListener(this);

        btnNext = (ImageButton) findViewById(R.id.image_view_btnnext);
        btnNext.setOnClickListener(this);

        mZoomView = (TouchImageView) findViewById(R.id.zoomview);

        pictureInfos = ServerCommunicator.getInstance(updateProgressBarHandler).getPictureInfos();

        if ((pictureInfos == null) || pictureInfos.isEmpty()) {
            startThreadGetPictureInfos();
        } else {
            currentPosition = Utility.getIndexOfPictureInfo(pictureInfos, latestFileView);
            startThreadToLoadImage();
        }
    }


    /* (non-Javadoc)
      * @see android.app.Activity#onRestart()
      */
    @Override
    protected void onRestart() {
        super.onRestart();
        initialize();
    }

    private void initialize() {
        Configuration.prepareConfiguration(this);
        DataAccess.getInstance().initializeDatabase(this);
        Configuration.setStateOfClient(StateOfClient.OFFLINE);
        onStop = false;
        isSwiping = false;
        waitingImageLoad = "";
        modeOfRun = ModeOfRun.IDLE;
        //Log.wtf(TAG, "ImageSwiper initialize()");
        downloadThread = new DownloadPicturesThread(pictureDownloadedHandler, stopDownloadThreadUnexpectly);
    }

    @Override
    public void onClick(View view) {
        if (view == btnBack)
            swipeImage(ModeOfSwipe.BACK);
        else if (view == btnNext)
            swipeImage(ModeOfSwipe.NEXT);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
            swipeImage(ModeOfSwipe.BACK);
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
            swipeImage(ModeOfSwipe.NEXT);
            return true;

        } else if (keyCode == KeyEvent.KEYCODE_BACK) {
            //Log.wtf(TAG, "ketCode:" + keyCode);

            if (!onStop) {
                m_ProgressDialog = Utility.getProgressDialog(ImageSwiper.this, Configuration.getRes());
                onStop = true;
                if (Configuration.getStateOfClient() == StateOfClient.DOWNLOADING_PICTURE) {
                    Configuration.setStateOfClient(StateOfClient.CANCEL_DOWNLOAD);
                }

                if (downloadThread.isAlive())
                    downloadThread.stopThread();

                quit();

                return super.onKeyDown(keyCode, event);

            } else
                return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    public void quit() {
        super.finish();
        downloadThread.stopThread();
    }

    /* public void finish() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("do you really want to exit?");
        builder.setCancelable(false);
        builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                quit();
            }
        });
        builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
    }*/


    private void swipeImage(ModeOfSwipe modeOfSwipe) {
        this.modeOfSwipe = modeOfSwipe;
        try {
            if (!isSwiping) {
                isSwiping = true;

                currentPosition = swipePosistion(modeOfSwipe, currentPosition);
                PictureInfo selectedItem = pictureInfos.get(currentPosition);
                if (selectedItem.isDownloaded()) {
                    startThreadToLoadImage();
                } else {
                    m_ProgressDialog = showWaitingDialog();

                    this.waitingImageLoad = selectedItem.getTitle();
                }
            }
        } catch (Exception e) {
            Utility.getAlertDialog(ImageSwiper.this, Configuration.getRes(),
                    e.getMessage());
        }

    }

    @Override
    public void handleSwipeEvent(EventObject e) {
        swipeImage((ModeOfSwipe) e.getSource());
    }

    private int swipePosistion(ModeOfSwipe modeOfSwipe, int currentPosition) {
        int nextPosition = currentPosition;
        if (modeOfSwipe == ModeOfSwipe.BACK)
            nextPosition--;
        else if (modeOfSwipe == ModeOfSwipe.NEXT)
            nextPosition++;
        if (nextPosition >= pictureInfos.size())
            nextPosition = 0;
        if (nextPosition < 0)
            nextPosition = pictureInfos.size() - 1;
        return nextPosition;
    }

    /*
      * (non-Javadoc)
      *
      * @see android.app.Activity#onStop()
      */
    @Override
    protected void onStop() {

        //Log.wtf(TAG, "onStop()");

        SettingManager.getInstance().setLatestSwipePath(
                getPreferences(MODE_PRIVATE), swipePath);

        SettingManager.getInstance().setLatestFileView(
                getPreferences(MODE_PRIVATE), latestFileView);

        if (!onStop) {
            onStop = true;
            if (Configuration.getStateOfClient() == StateOfClient.DOWNLOADING_PICTURE) {
                Configuration.setStateOfClient(StateOfClient.CANCEL_DOWNLOAD);
            }

            if (downloadThread.isAlive())
                downloadThread.stopThread();
        }

        if (m_ProgressDialog != null) {
            m_ProgressDialog.dismiss();
        }

        super.onStop();
    }

    /*
      * (non-Javadoc)
      *
      * @see android.app.Activity#onStop()
      */
    @Override
    protected void onDestroy() {
        super.onDestroy();

        //Log.wtf(TAG, "onDestroy");

        if (mBitmap != null)
            mBitmap.recycle();

        mZoomView.setOnTouchListener(null);
    }

    /**
     * Start new thread to login when activity is restart
     */
    private void startThreadGetPictureInfos() {
        modeOfRun = ModeOfRun.GET_SEVER_INFORMATION;
        Thread thread = new Thread(this);
        thread.start();

        // initialize progress bar
        m_ProgressDialog = Utility.getProgressBar(ImageSwiper.this, Configuration.getRes());
        m_ProgressDialog.show();
    }

    private void startThreadToLoadImage() {
        modeOfRun = ModeOfRun.LOAD_PICTURE;

        addItems2DownloadQueue();

        Thread thread = new Thread(this);
        thread.start();

        if (waitingImageLoad == "") {
            // initialize progress bar
            m_ProgressDialog = Utility.getProgressDialog(ImageSwiper.this, Configuration.getRes());
            m_ProgressDialog.show();
        }
    }

    /*
      * Get data from server & notified to handler when finished
      *
      * @see java.lang.Runnable#run()
      */
    public void run() {
        if (modeOfRun == ModeOfRun.LOAD_PICTURE) {
            loadImage();
        } else if (modeOfRun == ModeOfRun.GET_SEVER_INFORMATION) {
            getServerInformation();
        }
    }


    private void getServerInformation() {
        String message = Configuration.GET_DATA_SUCCESSFUL_MESSAGE;

        try {
            ServerCommunicator communicator = ServerCommunicator.getInstance(updateProgressBarHandler);
            pictureInfos = communicator.getPictureInfos(username, password, swipePath);

        } catch (ServerException e) {
            message = e.getErrorMessage();
        } catch (NetworkException e) {
            message = e.getErrorMessage();
        } catch (Exception e) {
            message = e.getMessage();
        }

        Bundle bundle = new Bundle();
        bundle.putString(Configuration.SERVER_MESSAGE_KEY, message);
        Message msg = new Message();
        msg.setData(bundle);
        getInformationFinishedHandler.sendMessage(msg);
    }

    private void loadImage() {
        String message = Configuration.LOAD_PICTURE_SUCCESSFUL_MESSAGE;

        try {
            if (mBitmap != null)
                mBitmap.recycle();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mBitmap = pictureInfos.get(currentPosition).getImage();
        } catch (OutOfMemoryError e) {
            message = Configuration.getRes().getString(
                    R.string.out_of_memory_when_view_picture);
        }

        Bundle bundle = new Bundle();
        bundle.putString(Configuration.LOAD_PICTURE_MESSAGE_KEY, message);
        Message msg = new Message();
        msg.setData(bundle);
        loadImageFinishedHandle.sendMessage(msg);
    }

    /**
     * When auto delete service not success dismiss progress dialog, and showing
     * the aler dialog
     */
    private Handler loadImageFinishedHandle = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            modeOfRun = ModeOfRun.IDLE;
            isSwiping = false;
            waitingImageLoad = "";
            String message = msg.getData().getString(
                    Configuration.LOAD_PICTURE_MESSAGE_KEY);
            if (!message.equals(Configuration.LOAD_PICTURE_SUCCESSFUL_MESSAGE)) {
                m_ProgressDialog.dismiss();
                Utility.getAlertDialog(ImageSwiper.this,
                        Configuration.getRes(), message).show();
            } else {
                updateCurrentTitle();

                Bitmap bitmap = mZoomView.getImage();
                if (bitmap != null)
                    bitmap.recycle();

                mZoomView.setImage(mBitmap);

                m_ProgressDialog.dismiss();
            }
        }
    };

    /**
     * update progress of progress bar
     */
    private Handler updateProgressBarHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int progress = msg.getData().getInt(
                    Configuration.PROGRESS_BAR_PERCENT);
            String downloadHeader = msg.getData().getString(
                    Configuration.DOWNLOAD_HEADER);
            if (m_ProgressDialog != null) {
                m_ProgressDialog.setProgress(progress);
                m_ProgressDialog.setMessage(downloadHeader);
            }
        }
    };

    /**
     * When load data from server finished dismiss progress dialog
     */
    private Handler getInformationFinishedHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            modeOfRun = ModeOfRun.IDLE;
            String message = msg.getData().getString(
                    Configuration.SERVER_MESSAGE_KEY);
            if (!message.equals(Configuration.GET_DATA_SUCCESSFUL_MESSAGE)) {
                m_ProgressDialog.dismiss();
                Utility.getAlertDialog(ImageSwiper.this,
                        Configuration.getRes(), message).show();
            } else {
                currentPosition = Utility.getIndexOfPictureInfo(pictureInfos,
                        latestFileView);
                addItems2DownloadQueue();

                loadFirstImagePicture();

                m_ProgressDialog.dismiss();
            }
        }
    };

    /**
     * When download file from server finished dismiss progress dialog
     */
    private Handler pictureDownloadedHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (onStop) {
                return;
            }

            String fileTitle = msg.getData().getString(Configuration.LOCAL_FILE_PATH);
            if (fileTitle.equalsIgnoreCase(waitingImageLoad)) {
                m_ProgressDialog.setMessage(Configuration.getRes().getString(R.string.progress_bar_description));
                startThreadToLoadImage();
            }
        }
    };

    /**
     * When download file from server finished dismiss progress dialog
     */
    private Handler stopDownloadThreadUnexpectly = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (onStop)
                return;
            String message = Configuration.getRes().getString(
                    R.string.stop_download_thread_unexpectedly)
                    + "\n";
            message += msg.getData().getString(
                    Configuration.STOP_DOWNLOAD_THREAD_MESSAGE_KEY);
            Utility.getAlertDialog(ImageSwiper.this, Configuration.getRes(),
                    message).show();
        }
    };

    private void loadFirstImagePicture() {
        try {
            PictureInfo selectedItem = pictureInfos.get(currentPosition);
            if (!selectedItem.isDownloaded())
                downloadThread.addDonwloadItem(selectedItem);

            updateCurrentTitle();
            Bitmap bitmap = mZoomView.getImage();
            if (bitmap != null)
                bitmap.recycle();

            mZoomView.setImage(selectedItem.getImage());
        } catch (OutOfMemoryError e) {
            Utility.getAlertDialog(
                    ImageSwiper.this,
                    Configuration.getRes(),
                    Configuration.getRes().getString(
                            R.string.out_of_memory_when_view_picture)).show();
        }
    }

    private void addItems2DownloadQueue() {
        if (pictureInfos.size() > 0) {
            int nextPosition = swipePosistion(ModeOfSwipe.NEXT, currentPosition);
            downloadThread.addDonwloadItem(pictureInfos.get(nextPosition));
            int backPosition = swipePosistion(ModeOfSwipe.BACK, currentPosition);
            downloadThread.addDonwloadItem(pictureInfos.get(backPosition));
            if (!downloadThread.isAlive())
                downloadThread.start();
        }
    }

    private void updateCurrentTitle() {
        if (pictureInfos.size() > 0) {
            PictureInfo selectedItem = pictureInfos.get(currentPosition);

            String app_name = Configuration.getRes().getString(
                    R.string.app_name);

            String title = app_name + " - ";
            title += (currentPosition + 1) + "/" + pictureInfos.size() + " - ";
            title += selectedItem.getTitle();
            setTitle(title);

            TextView imageTitle = (TextView) findViewById(R.id.image_view_title);
            imageTitle.setText(selectedItem.getTitle());
        }
    }

    private ProgressDialog showWaitingDialog() {
        Resources res = Configuration.getRes();

        String progressBarTitle = res.getString(R.string.progress_bar_title);
        String progressBarDescription = res
                .getString(R.string.progress_bar_dowloading_description);

        ProgressDialog progressDialog = ProgressDialog.show(ImageSwiper.this,
                progressBarTitle, progressBarDescription, true);

        progressDialog.setCancelable(true);
        progressDialog.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode,
                                 KeyEvent event) {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    revertConfiguration();
                    return false;
                }
                return true;
            }
        });

        return progressDialog;
    }

    protected void revertConfiguration() {
        if (waitingImageLoad != "") {
            isSwiping = false;
            waitingImageLoad = "";
            if (modeOfSwipe == ModeOfSwipe.BACK) {
                currentPosition = swipePosistion(ModeOfSwipe.NEXT,
                        currentPosition);
            } else if (modeOfSwipe == ModeOfSwipe.NEXT) {
                currentPosition = swipePosistion(ModeOfSwipe.BACK,
                        currentPosition);
            }
            updateCurrentTitle();
        }
    }
}
